#pragma once

#include <iostream>
#include <vector>
#include <string>
#include "thread.hpp"
#include <queue>
#include <unistd.h>
#include "lockGuard.hpp"
#include "log.hpp"

const int g_thread_num = 3;

//本质是：生产消费模型
template<class T>
class ThreadPool
{
public:
    pthread_mutex_t* getMutex()
    {
        return &lock_;
    }
    bool isEmpty()
    {
        return task_queue_.empty();
    }
    void waitCond()
    {
        pthread_cond_wait(&cond_, &lock_);
    }
    T getTask()
    {
        T t = task_queue_.front();
        task_queue_.pop();
        return t;
    }
public:
    ThreadPool(int thread_num = g_thread_num)
        :num_(thread_num)
    {
        pthread_mutex_init(&lock_, nullptr);
        pthread_cond_init(&cond_, nullptr);
        for (int i = 1; i <= num_; i++)
        {
            threads_.push_back(new Thread(i, routine, this));
        }
    }
    // 1. run()
    void run()
    {
        for (auto& iter : threads_)
        {
            iter->start();
            //std::cout << iter->name() << "启动成功" << std::endl;
            logMessage(NORMAL, "%s%s", iter->name().c_str(), "启动成功");
        }
    }
    // void* routine(void* args)
    // 线程池本身是一个生产消费模型
    // 消费过程
    static void* routine(void* args)
    {
        ThreadData* td = (ThreadData*)args;
        ThreadPool<T>* tp = (ThreadPool<T>*)td->args_;
        while (true)
        {
            T task;
            {
                lockGuard lockguard(tp->getMutex());
                while (tp->isEmpty()) tp->waitCond();

                // 读取任务
                task = tp->getTask();// 任务队列是共享的->将任务从从共享，拿到自己的私有空间
            }
            task(td->name_); 
        }
    }
    // 2. pushTask()
    // 生产过程
    void pushTask(const T& task)
    {
        lockGuard lockguard(&lock_);
        task_queue_.push(task);
        pthread_cond_signal(&cond_);
    }
    void joins()
    {
        for (auto& iter : threads_)
        {
            iter->join();
        }
    }
    void show()
    {
        std::cout << "可以传入this,让使用静态方法的线程,访问到线程池内的方法" << std::endl;
    }
    ~ThreadPool()
    {
        for (auto& iter : threads_)
        {
            iter->join();
            delete iter;
        }
        pthread_mutex_destroy(&lock_);
        pthread_cond_destroy(&cond_);
    }
private:
    std::vector<Thread*> threads_;
    int num_;
    std::queue<T> task_queue_;
    pthread_mutex_t lock_;
    pthread_cond_t cond_;
};